<?php
/**
 * Класс столбца таблицы.
 * @author nrnwest@gmail.com
 *
 */
class Arm_Grid_JqGrid_Col
{
    
    /**
     * Равно
     * @var string
     */
    const SEARCH_EQ = 'eq';
    /**
     * Не равно
     * @var string
     */
    const SEARCH_NE = 'ne';
    /**
     * Начинается с
     * @var string
     */
    const SEARCH_BW = 'bw';
    /**
     * Содержит.
     * @var string
     */
    const SEARCH_CN = 'cn';
    
    /**
     * Зарезивированные имена, js jqGrid
     * @var array
     */
    private $_reservName = array('_search', 'oper', 'groupOp', 'filters', 'sidx', 'sord', 'rows', 'page', 'nd');
    
    /**
     * Выравнивания.
     * @var string
     */
    private $_align = 'right';
    
    /**
     * Имя поля
     * @var string
     */
    private $_name;
    
    /**
     * Заголовок для столбца
     * @var string
     */
    private $_label;
    
    /**
     * Устанавливать ли данные в grid, по умолчанию
     * устанавливаются данные.
     * @var bool
     */
    private $_dataNoGrid = false;
    
    /**
     * Тип редактирования, какое поле применяется, text|select|...
     * @var string
     */
    private $_edittype=false;
    
    /**
     * Опиции для редактирования 
     * @var array
     */
    private $_editoptions=array();
    
    /**
     * Правила для редактирования
     * @var array
     */
    private $_editrules = array();
    
    /**
     * Сортировка в таблице.
     * @var bool
     */
    private $_sortable = true;
     
    /**
     * Поиск по столбцу установлен или нет, если установлен то указанны параметры 
     * поиска.
     * @var array
     */
    private $_search = array();
    
    /**
     * Форматирования.
     * @var string
     */
    private $_formatter = null;
    
    /**
     * Ширина поля
     * @var int
     */
    private $_width = null;
    
    /**
     * Сокрития поля
     * @var bool
     */
    private $_hidden = false;
    
    /**
     * Конструктор
     * @param string $name имя столбца
     * @param string $label заголовок столбца.
     */
    public function __construct($name, $label, array $config=array())
    {
        $this->setName($name);
        $this->setLabel($label);
     
        if($config !== array()) {   
            $this->_setConfig($config);
        }
    }
    
    /**
     * Установка поиска с конфига
     * @param string $options
     */
    protected function _setSearch($options)
    {
        if(is_string($options)){
            $this->setSearch();
        } else  {
            $this->setSearch($options);
        }
        return;
    }
    
    /**
     * Устаглвка с конфига поля редктирования
     * @param string $type
     * @param mixed $params
     */
    protected function _setEdit($type, $params)
    {
        if(is_array($params) === false) {
            $this->{'set' . $type}();
        }

        switch ($type) {
        	case 'edittext':
        	$size= null;
            $maxlength=null;
            if(isset($params['size'])) {
                $size = $params['size'];
            }
            if(isset($params['maxlength'])) {
                $maxlength = $params['maxlength'];
            }
            $this->setEditText($size,$maxlength);
        	break;
        	
        	case 'edittextarea':
        	$cols=null; 
        	$rows=null;
            if(isset($params['cols'])) {
                $cols = $params['cols'];
            }
            if(isset($params['rows'])) {
                $rows = $params['rows'];
            }
            $this->setEditTextarea($cols,$rows);
        	break;
        	
        	case 'editpassword':
            $cols=null; 
            $rows=null;
            if(isset($params['cols'])) {
                $cols = $params['cols'];
            }
            if(isset($params['rows'])) {
                $rows = $params['rows'];
            }
            $this->setEditPassword($cols,$rows);
            break;
            
            case 'editcheckbox':
            foreach ($params as $k=>$v)
            {
               $params[$k] = Arm_Translate::_($v); 
            }
            $this->setEditCheckbox($params);
            break;
            
            case 'editselect':
            $options = array(); 
            $multiple = false; 
            $size = 2;
           
            if(isset($params['options'])){
                if(is_string($params['options'])){
                    // если строка значит класс::метод
                    $array = explode('::',$params['options']);
                    if(count($array) !== 2) {
                        throw new Arm_Grid_JqGrid_Exception(Arm_Translate::_('для получения options данных, нужно указывать класс::метод'));
                    }
                    $class = new $array[0];
                    $options = $class->{$array[1]}();
                } else {
                // заданые парметры
                    foreach ($params['options'] as $k=>$v)  {
                        $params['options'][$k] = Arm_Translate::_($v);
                    }
                    $options = $params['options'];    
                }
            }
            
            if(isset($params['multiple'])){
                $multiple = (bool) $params['multiple'];
            }
            
            if(isset($params['size'])){
                $size = (int) $params['size'];
            }
            
            $this->setEditSelect($options,$multiple,$size);
            break;
        }
    }
    
    /**
     * Параметры для одного поля.
     * @param array $config
     */
    protected function _setConfig($config)
    {
        foreach ($config as $k=>$v) {
            $k = strtolower($k);
            if($k ===  'search'){
                $this->_setSearch($v);
                continue;
            }
            if($k === 'formatter'){
                $this->setFormatter($v);
            }
            if(strpos($k, 'edit') === 0) {
                $this->_setEdit($k, $v);
                continue;
            }
            if(is_array($v) === false) {
                $this->{'set'.$k}($v);
            }
        }
        
        return;
    }
    
    /**
     * Установка форматера.
     * formatter:'showlink', formatoptions:{target:'blank' baseLinkUrl:'/someurl.php', addParam: '&action=edit', idName:'id'}}
     * @param array $params
     */
    public function setFormatter($params)
    {
        if(isset($params['name']) === false) {
            throw new Arm_Grid_JqGrid_Exception(Arm_Translate::_('Не указан ключ name названия форматировщика'));
        }
        $name = $params['name'];
        $str = "formatter:'$name'";
        if(isset($params['params'])) {
            if(is_array($params['params']) === false) {
               throw new Arm_Grid_JqGrid_Exception(Arm_Translate::_('Параметры для форматирощика должны быть массивом')); 
            }
           $result = array();
           foreach ($params['params'] as $k=>$v) {
               $kp = strtolower($k); 
               if($kp==='addparam') {
                   $v = '&'  . ltrim($v,'&');
               }
               $result[] = $k . ":'$v'";
           }
           $str .= ', formatoptions:{' . implode(', ', $result) .'}';
        }
        $this->_formatter = $str;
        return;
    }
    
    /**
     * Ширина столбца
     * @param int $width
     * @return Arm_Grid_JqGrid_Col
     */
    public function setWidth($width)
    {
       $this->_width = $width;
       return $this;
    }
    
    /**
     * Установка выравневания
     * @param string $align right|left
     * @return Arm_Grid_JqGrid_Col
     */
    public function setAlign($align = 'right')
    {
        $this->_align = $align;
        return $this;
    }
    
    /**
     * Возвращает имя поля.
     * 
     * @return string
     */
    public function getName()
    {
        return $this->_name;
    }
    
    /**
     * Установка имени столбца.
     * 
     * @param string $name
     * @return Arm_Grid_JqGrid_Col
     */
    public function setName($name)
    {
        $ns = strtolower($name);
        if(array_search($ns, $this->_reservName) !== false) {
            throw new Arm_Grid_JqGrid_Exception(Arm_Translate::_('Зарезивированные имя столбца "%s" ', $name));
        }
        $this->_name = $name;
        return $this;
    }
    
    /**
     * Описания столбца
     * 
     * @return string
     */
    public function getLabel()
    {
        return $this->_label;
    }
    
    /**
     * Установка заголовка столбца.
     * 
     * @param string $label
     * @return Arm_Grid_JqGrid_Col
     */
    public function setLabel($label)
    {
        $this->_label = $label;
        return $this;
    }
    
    /**
     * Вывод строки поля для модели colModel
     * 
     * @return string
     */
    public function render()
    {
        $array = array();
        $array[] = 'name:'  . "'" . $this->_name . "'";
        $array[] = 'index:' . "'" . $this->_name . "'";
        
        if($this->_hidden) {
            $array[] = 'hidden:true';
        }
        if($this->_editrules !== array()) {
            $array[] = 'editrules:{' . implode(',', $this->_editrules) . '}';
        }
        if($this->_width !== null) {
            $array[] = 'width:' . $this->_width;
        }
        $array[]     = 'align:' . "'" . $this->_align . "'";
        // сортировка
        if($this->_sortable === false) {
            $array[] = 'sortable:false';
        }
        // форматирования
        if($this->_formatter  !== null) {
            $array[] = $this->_formatter;
        }
        // редактирования
        if($this->_edittype !== false) {
            $array[] = 'editable:true';
            $array[] = 'edittype:' . '"' . $this->_edittype . '"';
            if($this->_editoptions !== array()) {
                $editOptions = array();
                foreach ($this->_editoptions as $k=>$v) {
                    if('multiple' === $k) {
                        continue;
                    }
                    $editOptions[] = $k . ':' . $v;
                }
                if($this->_edittype === 'text' or $this->_edittype === 'textarea') {
                    $array[] = 'editoptions:{' . implode(',', $editOptions) . '}';
                } elseif($this->_edittype === 'select') {
                    if(array_key_exists('multiple', $this->_editoptions)) {
                        $multiple = $this->_editoptions['multiple'] . ',';
                    } else {
                        $multiple = null;
                    }
                    $array[] = 'editoptions:{'.$multiple.'value:"' . implode(';', $editOptions) . '"}';
                } elseif($this->_edittype === 'checkbox') {
                    $array[] = 'editoptions:{value:"' . implode(':', $this->_editoptions) . '"}';
                }
            }
        }
       // поиск
       if($this->_search !== array()) {
           $serchParams = array();
           foreach ($this->_search as $v) {
               $serchParams[] = "'" . $v . "'";
           }
           $array[] = 'search:true';
           $array[] = 'searchoptions:{sopt:[' . implode(',', $serchParams) . ']}';  
       } else {
           $array[] = 'search:false';
       }

       $result = '{' . implode(', ', $array) . '}';
       return $result; 
    }
    

    /**
     * Сокрытия столбца
     * 
     * @param bool $set
     * @return Arm_Grid_JqGrid_Col
     */
    public function setHidden($set=true)
    {
        $set =  (bool) $set;
        $this->_hidden = $set;
        return $this;
    }
    
    /**
     * Установит правило обязательного заполнения поля через
     * форму grid
     * 
     * @return Arm_Grid_JqGrid_Col
     */
    public function setRequired()
    {
       $this->_editrules[] = 'required:true';
       return $this;
    }
    
    /**
     * Проверка в grid емаил данные или нет.
     * 
     * @return Arm_Grid_JqGrid_Col
     */
    public function setValidEmail()
    {
        $this->_editrules[] = 'email:true';
        return $this;
    }
    
    /**
     * Если поле скрытое в таблице, можно его показать при редактировании.
     * 
     * @return Arm_Grid_JqGrid_Col
     */
    public function setViewEdit()
    {
       $this->_editrules[] = 'edithidden:true';
       return $this;
    }
    
    /**
     * Если поле не нужно заполнять данными в grid данный метод
     * это установит. Это нужно для поля password, так как данные
     * обычно хранятся в зашифрованом виде.
     * 
     * @return Arm_Grid_JqGrid_Col
     */
    public function setDadaNoGrid($set = true)
    {
        $set = (bool) $set;
        $this->_dataNoGrid = $set;
        return $this;
    }
    
    /**
     * Если возвращает false, данные нужно установить
     * если true данные в grid не будут установленны
     * 
     * @return bool true не устанавливать данные, false устанавливать.
     */
    public function getDadaNoGrid()
    {
        return $this->_dataNoGrid;
    }
    
    /**
     * Сортировать в таблице
     * 
     * @param bool $set
     * @return Arm_Grid_JqGrid_Col
     */
    public function setSortable($set=true)
    {
       $set =  (bool) $set;
       $this->_sortable = $set;
       return $this;
    }
    
    /**
     * Установка поиска по столбцу
     * eq - равно, ne - не равно, bw - начинается с, cn содержит
     * @param array $options
     * @return Arm_Grid_JqGrid_Col
     */
    public function setSearch($options=array(self::SEARCH_EQ,self::SEARCH_NE,self::SEARCH_BW,self::SEARCH_CN))
    {
        $this->_search = $options;
        return $this;
    }
    
    /**
     * Тип поля для редактирования text
     * 
     * @return Arm_Grid_JqGrid_Col
     */
    public function setEditText($size=null,$maxlength=null)
    {
        $this->_edittype = 'text';
        if($size !== null and $maxlength !==null) {
            $this->_editoptions = array('size'=>$size, 'maxlength'=>$maxlength);
        }
        return $this;
    }
    
    /**
     * Тип поля для редактирования select
     * 
     * @param array $options array(значение=>описание...)
     * @param bool $multiple если нужно мульти выбор устновите true
     * @param int  $size
     * @return Arm_Grid_JqGrid_Col
     */
    public function setEditSelect($options, $multiple = false, $size = 2)
    {
        if($multiple) {
            $options['multiple'] = 'multiple:true, size:'.$size;
        }
        $this->_editoptions = $options;
        $this->_edittype    = 'select';
        return $this;
    }
    
    /**
     * Тип поля checkbox
     * 
     * @param array $options array('да', 'нет')
     * @return Arm_Grid_JqGrid_Col
     */
    public function setEditCheckbox($options)
    {
        $this->_edittype    = 'checkbox';
        $this->_editoptions = $options;
        return $this;
    }
    
    /**
     * Тип поля для редактирования textarea
     * 
     * @return Arm_Grid_JqGrid_Col
     */
    public function setEditTextarea($cols=null, $rows=null)
    {
        $this->_edittype    = 'textarea';
        if($cols !== null and $rows !== null) {
            $this->_editoptions = array('cols'=>$cols, 'rows'=>$rows);
        }
        return $this;
    }
    
    /**
     * Установка поля типа password
     * @param int $cols
     * @param int $rows
     * @return Arm_Grid_JqGrid_Col
     */
    public function setEditPassword($cols=null, $rows=null)
    {
        $this->_edittype    = 'password';
        if($cols !== null and $rows !== null) {
            $this->_editoptions = array('cols'=>$cols, 'rows'=>$rows);
        }
        return $this;
    }
}